package com.xueqiu.movieplaymanagersystem.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import com.xueqiu.movieplaymanagersystem.entity.Blog;
import com.xueqiu.movieplaymanagersystem.entity.Type;
import com.xueqiu.movieplaymanagersystem.mapper.BlogMapper;
import com.xueqiu.movieplaymanagersystem.service.BlogService;
import com.xueqiu.movieplaymanagersystem.service.BlogTagService;
import com.xueqiu.movieplaymanagersystem.service.CommentService;
import com.xueqiu.movieplaymanagersystem.service.TypesService;
import com.xueqiu.movieplaymanagersystem.utils.HtmlToText;
import com.xueqiu.movieplaymanagersystem.utils.MarkdownUtils;
import com.xueqiu.movieplaymanagersystem.utils.StringUtils;
import com.xueqiu.movieplaymanagersystem.utils.UUIDUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author xueqiu
 */
@Service
@Slf4j
public class BlogServiceImpl implements BlogService {
    @Autowired
    private BlogMapper blogMapper;
    @Autowired
    private BlogTagService blogTagService;
    @Autowired
    private CommentService commentService;

    private TypesService typesService;
    private StringRedisTemplate redisTemplate;

    @Autowired
    public void setRedisTemplate(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 注解@Qualifier("typesService")
     * 用于指定依赖对象的限定符
     * 当存在多个类型兼容的依赖对象时，可以使用 @Qualifier 注解来指定具体要注入的对象
     * 指定了要注入的 TypesService 对象的限定符为 "typesService"，以区分其他同类型的依赖对象
     *
     * @param typesService 类别服务
     */
    @Autowired
    public void setTypesService(
            @Qualifier("typesService")
            TypesService typesService
    ) {
        this.typesService = typesService;
    }

    /**
     * 发布新闻
     *
     * @param originData 数据源
     * @return 是否发布
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean publish(Blog originData) {
        return publishOrSave(originData, "publish");
    }

    /**
     * 保存新闻
     *
     * @param originData 数据源
     * @return 是否保存
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(Blog originData) {
        return publishOrSave(originData, "save");
    }

    /**
     * 发布和更新的主要实现
     *
     * @param originData 数据源
     * @param method     状态类型，是保存，还是发布
     * @return 发布或更新是否成功
     */
    private boolean publishOrSave(Blog originData, String method) {
        //判断所选类型是否存在，不存在则返回false
        Type type = typesService.findById(originData.getTypeId());
        if (type == null) {
            return false;
        }

        //获得“正文文本”
        String content = originData.getContent();
        //获得“描述文本”；如果创作者没有写，那么默认是从正文截取的一部分；由后端生成
        String description = originData.getDescription();

        //判断“描述文本”是否为空；如果创作者没有写，那么默认是从正文截取的一部分；由后端生成
        if (StringUtils.isNullOrEmptyOrOnlyWhiteSpace(description)) {
            //将markdown格式的正文文本转换成html格式
            String html = MarkdownUtils.markdownToHtml(content);
            //将html格式的正文文本转换成txt格式
            String convert = HtmlToText.convert(html);
            //使用spring框架的StringUtils字符串工具类，去除多余空格和多余换行
            String trimAllWhitespace = org.springframework.util.StringUtils.trimAllWhitespace(convert);
            //人为指定“描述文本”的最大长度是正文的前160字符，并且拼上"..."
            description = trimAllWhitespace.substring(0, 160) + "...";
            //设置“描述文本”
            originData.setDescription(description);
        }


        //判断blog的“id非null且不为''”；
        if (!StringUtils.isNullOrEmptyOrOnlyWhiteSpace(originData.getId())) {
            //符合则为“修改”操作
            //判断blog的id是否正确
            if (blogMapper.selectBlogNotNull(originData.getId()) == null) {
                return false;
            }
            //修改更新时间
            originData.setUpdateDate(new Date());
            //修改保存状态
            originData.setSave("save".equals(method));
            //获取tagsIds
            List<String> tagsIdList = originData.getTagId();
            //如果tagsIds不存在，说明tagsIds为空，初始化tagsIds
            if (tagsIdList == null) {
                tagsIdList = new ArrayList<>();
            }
            //执行对blog_tag表的更新
            int updateBlogTagRelationship = blogTagService.editBatch(tagsIdList, originData.getId());
            int updateBlog;
            if (updateBlogTagRelationship >= 1) {
                //执行对blog表的更新
                updateBlog = blogMapper.update(originData);
                if (updateBlog == 1) {
                    //将正文内容进行格式转换
                    String html = MarkdownUtils.markdownToHtmlExtensions(originData.getContent());
                    //更新缓存
                    redisTemplate.boundHashOps("movieplaymanagersystem").put(originData.getId(), html);
                    //将生成的描述文本存入缓存；键值对是String id:String description
                    redisTemplate.boundHashOps("description").put(originData.getId(), description);
                    return true;
                } else {
                    //更新新闻操作失败
                    return false;
                }
            } else {
                //更新新闻与标签关系操作失败
                return false;
            }
        } else {
            //不符合则为“首次发表”操作；id是使用UUID生成而不是自增
            originData.setId(UUIDUtils.uuid());
            //创建日期
            originData.setCreateDate(new Date());
            //修改日期与创建日期一致
            originData.setUpdateDate(new Date());
            //初始化点赞量为零
            originData.setLike(0);
            //初始化访问量为零
            originData.setViews(0);
            //初始化评论总数为零
            originData.setCommentCount(0);
            //判断状态类型；设置状态类型
            originData.setSave("save".equals(method));
            //判断是否打上标签
            // if (movieplaymanagersystem.getTagId() != null && movieplaymanagersystem.getTagId().size() != 0) {
            if (!CollectionUtils.isEmpty(originData.getTagId())) {
                //绑定新闻与标签，标签可以有很多
                int insertBlogTagRelationship = blogTagService.saveBatch(originData.getTagId(), originData.getId());
                if (insertBlogTagRelationship <= 0) {
                    //新增新闻与标签关系操作失败
                    return false;
                }
            }
            int isInsert = blogMapper.insert(originData);
            if (isInsert == 1) {
                //获取正文内容并转换为html格式
                String html = MarkdownUtils.markdownToHtmlExtensions(originData.getContent());
                //将正文内容存入缓存
                redisTemplate.boundHashOps("movieplaymanagersystem").put(originData.getId(), html);
                //将生成的描述文本存入缓存；键值对是String id:String description
                redisTemplate.boundHashOps("description").put(originData.getId(), description);
                return true;
            } else {
                //新增新闻操作失败
                return false;
            }
        }
    }

    /**
     * 更新访问量根据新闻id
     *
     * @param id 新闻id
     * @return 更新条数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean editViewsById(String id) {
        return blogMapper.updateViewsById(id) == 1;
    }

    /**
     * 更新点赞量根据新闻id
     *
     * @param id 新闻id
     * @return 更新条数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean editLikesById(String id) {
        return blogMapper.updateLikesById(id) == 1;
    }

    /**
     * 根据id删除单条数据
     *
     * @param id 标签id
     * @return 删除条数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeById(String id) {
        int delete = blogMapper.deleteById(id);
        if (delete == 1) {
            /*
            boundHashOps() 删除 Redis 中的一个哈希表（Hash）中的指定键值对
            "movieplaymanagersystem" 是哈希表的名称，id 是要删除的键
            通过调用 delete(id) 方法，可以从名为 "movieplaymanagersystem" 的哈希表中删除键为 id 的项
             */
            redisTemplate.boundHashOps("movieplaymanagersystem").delete(id);
            redisTemplate.boundHashOps("description").delete(id);
            return true;
        }
        return false;
    }

    /**
     * 批量删除根据复数新闻id
     *
     * @param idList 复数新闻id
     * @return 删除条数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeByIdBatch(List<String> idList) {
        int delete = blogMapper.deleteByIdBatch(idList);
        if (delete == idList.size()) {
            /*
            boundHashOps() 删除 Redis 中的一个哈希表（Hash）中的指定键值对
            "movieplaymanagersystem" 是哈希表的名称，blogId 是要删除的键
            通过调用 delete(blogId) 方法，可以从名为 "movieplaymanagersystem" 的哈希表中删除键为 blogId 的项
             */
            redisTemplate.boundHashOps("movieplaymanagersystem").delete(idList);
            redisTemplate.boundHashOps("description").delete(idList);
            return delete;
        }
        return -1;
    }

    /**
     * 根据id查询
     *
     * @param id 新闻id
     * @return 单个查询结果；可能为空
     */
    @Override
    @Transactional(readOnly = true)
    public Blog findById(String id) {
        //查询除了描述字段的所有信息；正文字段的格式是TEXT
        Blog blog = blogMapper.selectById(id);

        if (blog == null) {
            return null;
        }
        //获取描述内容
        String description = (String) redisTemplate.boundHashOps("description").get(blog.getId());

        if (description == null) {
            description = blogMapper.selectDescriptionById(blog.getId());

            redisTemplate.boundHashOps("description").put(blog.getId(), description);
        }
        blog.setDescription(description);
        log.info("BlogServiceImpl findById description ----> {}",description);
        return blog;
    }

    /**
     * 查询单个新闻全部信息，根据新闻id
     *
     * @param id 新闻id
     * @return 单个新闻全部信息
     */
    @Override
    @Transactional(readOnly = true)
    public Blog findDetailById(String id) {
        //查除了正文字段外的所有信息；描述字段格式是TEXT
        Blog blog = blogMapper.selectDetailById(id);

        if (blog == null) {
            return null;
        }
        //从缓存中获取正文内容；html格式
        String html = (String) redisTemplate.boundHashOps("movieplaymanagersystem").get(blog.getId());

        //如果缓存的正文内容为空；那就从数据库中查找正文内容
        if (StringUtils.isNullOrEmptyOrOnlyWhiteSpace(html)) {
            html = MarkdownUtils.markdownToHtmlExtensions(blogMapper.selectContentById(blog.getId()));
        }
        //将正文内容放入实体类
        blog.setContent(html);
        //将评论数量放入实体类
        blog.setCommentCount(commentService.findCountByBlogId(id));
        return blog;
    }

    /**
     * 分页查询若干新闻，通过关键字；
     * 关键字出现在标题或者正文
     *
     * @param keyWord 关键字
     * @param page    当前页
     * @param limit   当前页数据条数
     * @return 结果列表
     */
    @Override
    @Transactional(readOnly = true)
    public PageInfo<Blog> findByKeyWord(String keyWord, int page, int limit) {
        //避免关键字过长
        if (keyWord.length() > 10) {
            //截取前10个字符当作关键字
            keyWord = keyWord.substring(0, 10);
        }

        PageInfo<Blog> resultPageInfo = findByKeyWordOrByPage(keyWord, page, limit, "query");
        log.info("BlogServiceImpl findByKeyWord resultPageInfo ----> {}",resultPageInfo);
        return resultPageInfo;
    }

    /**
     * 分页查询已发布的新闻
     *
     * @param page  指定当前页
     * @param limit 指定每页展示数量
     * @return 新闻列表
     */
    @Override
    @Transactional(readOnly = true)
    public PageInfo<Blog> findAllPublished(int page, int limit) {
        PageInfo<Blog> resultPageInfo = findByKeyWordOrByPage(null, page, limit, "index");
        return resultPageInfo;
    }

    /**
     * 查询新闻，根据标题关键字和类型id和是否推荐状态；使用了PageHelper.startPage
     * 如果标题关键字和类别id都为null，那么不进行title字段和type_id字段的条件限制
     *
     * @param keyWord   标题关键字
     * @param typeId    类型id
     * @param isCommend 是否推荐状态
     * @param page      当前页
     * @param limit     每页显示数量
     * @return 新闻列表，可能为空
     */
    @Override
    @Transactional(readOnly = true)
    public PageInfo<Blog> findByKeyWordAndTypeIdAndCommend(String keyWord, String typeId, boolean isCommend, int page, int limit) {
        PageInfo<Blog> resultPageInfo = null;
        try (Page<Blog> originPage = PageHelper.startPage(page, limit)) {
            blogMapper.selectByKeyWordAndTypeIdAndCommend(keyWord, typeId, isCommend);
            List<Blog> originList = originPage.getResult();
            resultPageInfo = new PageInfo<>(originList);
        }
        log.info("BlogServiceImpl findByKeyWordAndTypeIdAndCommend resultPageInfo ----> {}",resultPageInfo);
        return resultPageInfo;
    }

    /**
     * 分页查询若干新闻根据类别id
     *
     * @param typeId 类别id
     * @param page   当前页
     * @param limit  当前页展示条数
     * @return 新闻列表
     */
    @Override
    @Transactional(readOnly = true)
    public PageInfo<Blog> findByTypeId(String typeId, int page, int limit) {
        PageInfo<Blog> resultPageInfo = findByTypeIdOrTagId(typeId, page, limit, "type");
        log.info("BlogServiceImpl findByTypeId resultPageInfo ----> {}",resultPageInfo);
        return resultPageInfo;
    }

    /**
     * 查询若干新闻，根据标签id下指定范围的新闻id
     *
     * @param tagId 标签id
     * @param page  当前页
     * @param limit 当前页展示条数
     * @return 新闻列表
     */
    @Override
    @Transactional(readOnly = true)
    public PageInfo<Blog> findByTagId(String tagId, int page, int limit) {
        return findByTypeIdOrTagId(tagId, page, limit, "tag");
    }

    /**
     * 查询所有推荐的新闻
     *
     * @return 推荐的新闻列表
     */
    @Override
    @Transactional(readOnly = true)
    public List<Blog> findByCommend() {
        return blogMapper.selectByCommend();
    }

    /**
     * 查询访问量最多的1个新闻
     * 使用排序和分页实现
     *
     * @return 访问量最多的1个新闻
     */
    @Override
    @Transactional(readOnly = true)
    public Blog findTopOneViews() {
        Blog blog = blogMapper.selectTopOneViews();
        log.info("BlogServiceImpl findTopOneViews blog ----> {}",blog);
        return blog;
    }

    /**
     * 查询点赞量优先的最多点赞数的前6名新闻
     * 访问量优先级低于点赞量
     * 使用排序和分页实现
     *
     * @return 前6名新闻
     */
    @Override
    @Transactional(readOnly = true)
    public List<Blog> findTopSixLikes() {
        List<Blog> originList = blogMapper.selectTopSixLikes();
        log.info("BlogServiceImpl findTopSixLikes blog ----> {}",originList);
        return originList;
    }

    /**
     * 查询被推荐的访问量前4名的新闻
     * 使用排序和分页实现
     *
     * @return 前4名新闻
     */
    @Override
    @Transactional(readOnly = true)
    public List<Blog> findTopFourViewsWithCommend() {
        return blogMapper.selectTopFourViewsWithCommend();
    }

    /**
     * 查询“被排除的新闻”的类别下的所有新闻列表，但是剔除“被排除的新闻”
     * 如果不存在列表
     * 那就查询“被排除的新闻”的标签组下的所有新闻列表，同样剔除“被排除的新闻”
     * <p>
     * 如果二者同时存在，则进行元素合并；重点在元素合并
     *
     * @param typeId          类别id
     * @param eliminateBlogId 被排除的新闻id
     * @param tagIdsArray     标签组，元素是标签id
     * @return 除了该新闻id代表的，以外的所有新闻
     */
    @Override
    @Transactional(readOnly = true)
    public List<Blog> findEliminateBlogByTypeIdAndTagId(String typeId, String eliminateBlogId, String[] tagIdsArray) {
        //查询当前类别下除了该新闻id代表的，以外的所有新闻
        List<Blog> originListByTypeId = blogMapper.selectByTypeIdAndBlogIdWithoutEliminateBlog(typeId, eliminateBlogId);

        //根据标签id查询，同时在结果中排除指定新闻id；查询结果限定为前6条
        List<Blog> originListByTagIdList = null;
        if (tagIdsArray != null && tagIdsArray.length != 0) {
            List<String> tagIdList = Arrays.asList(tagIdsArray);
            originListByTagIdList = blogMapper.selectByTagIdList(tagIdList, eliminateBlogId);
        }

        //两种查询结果的判断
        if (CollectionUtils.isEmpty(originListByTypeId)) {
            //如果类别查询列表空，那就返回标签查询列表；即使标签查询列表空
            return originListByTagIdList;
        } else if (CollectionUtils.isEmpty(originListByTagIdList)) {
            //如果标签查询列表空，那就返回类别查询列表；即使类别查询列表空
            return originListByTypeId;
        }

        //克隆临时列表；
        List<Blog> originListByTagIdListCopy = new ArrayList<Blog>();
        Collections.copy(originListByTagIdListCopy, originListByTagIdList);

        //利用临时列表对originListByTypeId进行元素过滤
        List<Blog> originListByTypeIdUnique = originListByTypeId.parallelStream()
                //对originListByTypeId中的元素进行过滤
                .filter(
                        //如果elementOfByType元素的标题，在originListByTagIdListCopy的所有元素中找不到；那就收集elementOfByType元素
                        (elementOfByType) -> originListByTagIdListCopy.parallelStream().noneMatch((elementOfByTag) -> elementOfByTag.getTitle().equals(elementOfByType.getTitle()))
                ).collect(Collectors.toList());

        //加入过滤后的元素；相当于把两种查询的结果汇总到一起，并进行了“去重”
        originListByTagIdList.addAll(originListByTypeIdUnique);

        //进行自定义规则排序；按访问量从小到大排序；并截取前8名
        List<Blog> resultList = originListByTagIdList.parallelStream()
                .sorted((otherElement, thisElement) -> (int) (thisElement.getViews() - otherElement.getViews()))
                .limit(8)
                .collect(Collectors.toList());

        return resultList;
    }

    /**
     * 查询该新闻的在数据库中的前一个新闻
     * 通过比较id实现和分页
     *
     * @param id 该新闻id
     * @return 前一个新闻
     */
    @Override
    @Transactional(readOnly = true)
    public Blog findBeforeById(String id) {
        return blogMapper.selectBeforeById(id);
    }

    /**
     * 查询该新闻的在数据库中的后一个新闻
     * 通过比较id实现和分页
     *
     * @param id 该新闻id
     * @return 后一个新闻
     */
    @Override
    @Transactional(readOnly = true)
    public Blog findAfterById(String id) {
        return blogMapper.selectAfterById(id);
    }

    /**
     * 随机获取若干数量新闻
     * SQL语句时查询全部新闻
     * 通过Collections.shuffle()方法达到随机目的。
     * 查询的字段是id, title, author, flag, views, `like`
     *
     * @param id 当前新闻id
     * @return 随机的6个元素的新闻列表；按照访问量从小到大排序
     */
    @Override
    @Transactional(readOnly = true)
    public List<Blog> findRandomNumsById(String id) {
        //查询全部元素
        List<Blog> blogList = blogMapper.selectRandom();
        //Collections.shuffle(blogList) 会对 blogList 中的元素进行随机打乱，即重新排列列表中的元素顺序，使其呈现随机的排列顺序。
        Collections.shuffle(blogList);

        List<Blog> resultList = blogList.parallelStream()
                //进行过滤；元素的id不与指定id一致的元素留下
                .filter(element -> !element.getId().equals(id))
                //截取前6个
                .limit(6)
                //排序；按照访问量从小到大
                .sorted((otherElement, thisElement) -> (int) (thisElement.getViews() - otherElement.getViews()))
                .collect(Collectors.toList());

        return resultList;
    }

    /**
     * 查询新闻正文内容根据新闻id
     *
     * @param id 新闻id
     * @return 新闻正文内容
     */
    @Override
    @Transactional(readOnly = true)
    public Blog findContentById(String id) {
        Blog blog = blogMapper.selectIdAndTitleById(id);

        if (blog != null) {
            String blogContent = (String) redisTemplate.boundHashOps("movieplaymanagersystem").get(blog.getId());

            if (StringUtils.isNullOrEmptyOrOnlyWhiteSpace(blogContent)) {
                blogContent = blogMapper.selectContentById(blog.getId());

                blogContent = MarkdownUtils.markdownToHtmlExtensions(blogContent);
                //将正文内容存入缓存
                redisTemplate.boundHashOps("movieplaymanagersystem").put(blog.getId(), blogContent);
            }
            blog.setContent(blogContent);
            log.info("BlogServiceImpl findContentById blogContent ----> {}",blogContent);
            return blog;
        }
        return null;
    }

    /**
     * 查询创建日期和标题
     * 按照从新到旧的顺序排序
     *
     * @return 创建日期和标题
     */
    @Override
    @Transactional(readOnly = true)
    public List<Blog> findAllOfTimeAndTitle() {
        return blogMapper.selectAllOfTimeAndTitle();
    }

    /**
     * 查询所有新闻数量，包含保存的新闻和发布的新闻
     *
     * @return 所有新闻数量
     */
    @Override
    @Transactional(readOnly = true)
    public Integer findCount() {
        Integer count = blogMapper.selectCount();
        log.info("BlogServiceImpl findCount count ----> {}",count);
        return count;
    }

    /**
     * 查询所有保存的新闻数量
     *
     * @return 所有保存的新闻数量
     */
    @Override
    @Transactional(readOnly = true)
    public Integer findSaveCount() {
        Integer count = blogMapper.selectSaveCount();
        log.info("BlogServiceImpl findSaveCount count ----> {}",count);
        return count;
    }

    /**
     * 查询所有已发布的新闻的数量
     *
     * @return 所有已发布的新闻的数量
     */
    @Override
    @Transactional(readOnly = true)
    public Integer findPublishCount() {
        Integer count = blogMapper.selectPublishCount();
        log.info("BlogServiceImpl findPublishCount count ----> {}",count);
        return count;
    }


    /**
     * 根据关键字分页查询若干新闻；或者分页查询全部新闻
     *
     * @param keyWord 关键字
     * @param page    起始页
     * @param limit   每页限制条数
     * @param method  命令种类；是关键字分页查询还是全部分页查询
     * @return 分页对象；其中会包含查询并封装好的实体类列表
     */
    private PageInfo<Blog> findByKeyWordOrByPage(String keyWord, int page, int limit, String method) {
        PageInfo<Blog> resultPageInfo = null;
        if ("query".equals(method)) {
            //根据关键词查询发布新闻；但是分页
            try (Page<Blog> originPage = PageHelper.startPage(page, limit)) {
                blogMapper.selectByKeyWord(keyWord);
                List<Blog> originResult = originPage.getResult();
                resultPageInfo = new PageInfo<>(originResult);
            }
        } else if ("index".equals(method)) {
            //查询所有发布新闻；但是分页
            try (Page<Blog> originPage = PageHelper.startPage(page, limit)) {
                blogMapper.selectAllPublished();
                List<Blog> originResult = originPage.getResult();
                resultPageInfo = new PageInfo<>(originResult);
            }
        }
        //判断查询结果是否为EMPTY
        if (CollectionUtils.isEmpty(resultPageInfo.getList())) {
            return null;
        }
        //将每一个新闻元素都添加描述
        setDescription(resultPageInfo);
        return resultPageInfo;
    }

    /**
     * 根据查询的新闻列表；获取每一个新闻的描述，并放进新闻实体类
     * 没有用stream()是因为元素操作涉及调用比较频繁；流不方便
     *
     * @param resultPageInfo 新闻列表
     */
    private void setDescription(PageInfo<Blog> resultPageInfo) {
        /*resultPageInfo.getList().forEach(new Consumer<Blog>() {
            @Override
            public void accept(Blog originData) {
                String description = (String) redisTemplate.boundHashOps("description").get(originData.getId());
                //如果缓存中不存在；则查询数据库
                if (description == null) {
                    description = blogMapper.selectDescriptionById(originData.getId());
                    //同时把描述存进缓存
                    redisTemplate.boundHashOps("description").put(originData.getId(), description);
                }
                originData.setDescription(description);
            }
        });*/
        List<Blog> resultList = resultPageInfo.getList();
        for (Blog element : resultList) {
            //优先查询缓存
            String description = (String) redisTemplate.boundHashOps("description").get(element.getId());
            //如果缓存中不存在；则查询数据库
            if (description == null) {
                description = blogMapper.selectDescriptionById(element.getId());
                //同时把描述存进缓存
                redisTemplate.boundHashOps("description").put(element.getId(), description);
            }
            //设置描述内容
            element.setDescription(description);
        }
        resultPageInfo.setList(resultList);
    }

    /**
     * 根据类型id分页查询若干新闻；或者根据标签id分页查询新闻
     *
     * @param amorphousId 不定型的id，可能是类型id，可能是标签id
     * @param page        当前页
     * @param limit       每页限制条数
     * @param method      命令种类；是关键字分页查询还是全部分页查询
     * @return 分页对象；其中会包含查询并封装好的实体类列表
     */
    private PageInfo<Blog> findByTypeIdOrTagId(String amorphousId, int page, int limit, String method) {
        PageInfo<Blog> resultPageInfo = null;
        if ("type".equals(method)) {
            try (Page<Blog> originPage = PageHelper.startPage(page, limit)) {
                blogMapper.selectByTypeId(amorphousId);
                List<Blog> originResult = originPage.getResult();
                resultPageInfo = new PageInfo<>(originResult);
            }
        } else if ("tag".equals(method)) {
            try (Page<Blog> originPage = PageHelper.startPage(page, limit)) {
                blogMapper.selectByTagId(amorphousId);
                List<Blog> originResult = originPage.getResult();
                resultPageInfo = new PageInfo<>(originResult);
            }
        }
        if (CollectionUtils.isEmpty(resultPageInfo.getList())) {
            return null;
        }
        //将每一个新闻元素都添加描述
        setDescription(resultPageInfo);
        return resultPageInfo;
    }
}
